package br.boicotando.server;

import org.hibernate.Session;
import org.hibernate.Transaction;

import br.boicotando.client.GerenciadorCliente;
import br.boicotando.dao.ClienteDao;
import br.boicotando.dao.ClienteDaoDB;
import br.boicotando.dao.DaoDB;
import br.boicotando.dominio.Cliente;
import br.boicotando.persistencia.ECliente;

import com.google.gwt.user.server.rpc.RemoteServiceServlet;

@SuppressWarnings("serial")
public class GerenciadorClienteImpl extends RemoteServiceServlet implements GerenciadorCliente {

	@Override
	public boolean login(String email, String senha) {
		Session sess = DaoDB.abreSessao();
		ClienteDao clienteDao = new ClienteDaoDB(sess);
		ECliente eCliente = clienteDao.consultarEmail(email);
		if (eCliente != null && eCliente.getSenha().equals(senha)) {
			sess.close();
            getThreadLocalRequest().getSession().setAttribute("CLIENTE_ID", eCliente.getId());
			return true;
		}
		sess.close();
		getThreadLocalRequest().getSession().removeAttribute("CLIENTE_ID");
		return false;
	}
	
	private void validaCliente(ClienteDao dao, Cliente cliente, boolean novo) {
		StringBuffer erros = new StringBuffer();
		
		if (cliente.getNome() == null || cliente.getNome().isEmpty()) {
			erros.append("O nome deve ser informado.\n");			
		}
		
		if (cliente.getSobrenome() == null || cliente.getSobrenome().isEmpty()) {
			erros.append("O sobrenome deve ser informado.\n");			
		}

		if (cliente.getCPF() == null) {
			erros.append("O CPF deve ser informado.\n");
		} else if (novo && dao.consultarCPF(cliente.getCPF()) != null) {
			erros.append(String.format("CPF (%s) já cadastrado.\n", cliente.getCPF()));
		}
		
		if (cliente.getDataNascimento() == null) {
			erros.append("A data de nascimento deve ser informada.\n");
		}
		
		if (cliente.getEmail() == null || cliente.getEmail().isEmpty()) {
			erros.append("O e-mail deve ser informado.\n");
		}
		
		if (cliente.getSenha() == null || cliente.getSenha().isEmpty()) {
			erros.append("O cliente precisa definir uma senha.\n");
		}
		
		if (cliente.getSexo() == null) {
			erros.append("O sexo do cliente precisa ser informado.\n");
		}
		
		/* TODO: O endereço não é obrigatório e um ciente pode ter vários.
		if (cliente.getEndereco() == null) {
			erros.append("O endereço deve ser informado.\n");
		} else {
			if (cliente.getEndereco().getCep() == null || cliente.getEndereco().getCep().isEmpty()) {
				erros.append("O CEP do endereço deve ser informado.\n");
			}
			
			if (cliente.getEndereco().getLogradouro() == null || cliente.getEndereco().getLogradouro().isEmpty()) {
				erros.append("O logradouro do endereço deve ser informado.\n");
			}
			
			if (cliente.getEndereco().getMunicipio() == null) {
				erros.append("O município do endereço deve ser informado.\n");
			} else {
				if (cliente.getEndereco().getMunicipio().getNome() == null || cliente.getEndereco().getMunicipio().getNome().isEmpty()) {
					erros.append("O nome do município deve ser informado.\n");
				}
				
				if (cliente.getEndereco().getMunicipio().getUnidadeFederativa() == null) {
					erros.append("A UF do município deve ser informada.\n");
				} else {
					if (cliente.getEndereco().getMunicipio().getUnidadeFederativa().getNome() == null || cliente.getEndereco().getMunicipio().getUnidadeFederativa().getNome().isEmpty()) {
						erros.append("O nome da UF do município deve ser informada.\n");
					}
					if (cliente.getEndereco().getMunicipio().getUnidadeFederativa().getSigla() == null || cliente.getEndereco().getMunicipio().getUnidadeFederativa().getSigla().isEmpty()) {
						erros.append("A sigla da UF do município deve ser informada.\n");
					}
				}
			}
			
			if (cliente.getEndereco().getNumero() == null) {
				erros.append("O numero do endereço deve ser informado.\n");
			}	
		}
		*/
		
		if (erros.length() > 0) {
			throw new RuntimeException(erros.toString());
		}
	}

	@Override
	public Cliente cadastraCliente(Cliente cliente) {
		Session sess = DaoDB.abreSessao();
		Transaction tran = sess.beginTransaction();
		ClienteDao clienteDao = new ClienteDaoDB(sess);
		validaCliente(clienteDao, cliente, true);
		ECliente eCliente = (ECliente) Bau.injetor().injetaA(cliente).emB(new ECliente());
		clienteDao.salvar(eCliente);
		eCliente = clienteDao.consultarEmail(cliente.getEmail());
		cliente = (Cliente) Bau.injetor().injetaA(eCliente).emB(new Cliente());
		tran.commit();
		sess.close();
        getThreadLocalRequest().getSession().setAttribute("CLIENTE_ID", eCliente.getId());
		return cliente;
	}

	@Override
	public Cliente alteraCliente(Cliente cliente) {
		ECliente eCliente;
		Session sess = DaoDB.abreSessao();
		Transaction tran;
		ClienteDao clienteDao = new ClienteDaoDB(sess);
		eCliente = clienteDao.consultarId(cliente.getId());
		if (eCliente == null) {
			cliente = null;
		} else {
			cliente.setSenha(eCliente.getSenha());
			validaCliente(clienteDao, cliente, false);
			tran = sess.beginTransaction();
			Bau.injetor().injetaA(cliente).emB(eCliente);
			clienteDao.salvar(eCliente);
			Bau.injetor().injetaA(eCliente).emB(cliente);
			tran.commit();
			sess.close();
		}
		return cliente;
	}

	@Override
	public Cliente alteraSenha(String senhaVelha, String senhaNova) {
		String id = (String) getThreadLocalRequest().getSession().getAttribute("CLIENTE_ID");
		if (id != null) {
			Session sess = DaoDB.abreSessao();
			ClienteDao clienteDao = new ClienteDaoDB(sess);
			ECliente eCliente = clienteDao.consultarId(id);
			if (eCliente != null && eCliente.getSenha().equals(senhaVelha)) {
				Cliente cliente;
				Transaction tran = sess.beginTransaction();
				eCliente.setSenha(senhaNova);
				clienteDao.salvar(eCliente);
				cliente = (Cliente) Bau.injetor().injetaA(eCliente).emB(new Cliente());
				tran.commit();
				sess.close();
				return cliente;
			}
			sess.close();
		}
		return null;
	}

	@Override
	public Cliente getUsuarioAtivo() {
		String id = (String) getThreadLocalRequest().getSession().getAttribute("CLIENTE_ID");
		if (id != null) {
			Session sess = DaoDB.abreSessao();
			ClienteDao clienteDao = new ClienteDaoDB(sess);
			ECliente eCliente = clienteDao.consultarId(id);
			sess.close();
			if (eCliente == null) {
				return null;
			} else {
				return (Cliente) Bau.injetor().injetaA(eCliente).emB(new Cliente());
			}
		}
		return null;
	}

	@Override
	public void logoff() {
		getThreadLocalRequest().getSession().removeAttribute("CLIENTE_ID");
	}

}
